package com.shm.leetcode;

import java.util.HashMap;
import java.util.Map;

/**
 * 1218. 最长定差子序列
 * 给你一个整数数组 arr 和一个整数 difference，请你找出并返回 arr 中最长等差子序列的长度，该子序列中相邻元素之间的差等于 difference 。
 *
 * 子序列 是指在不改变其余元素顺序的情况下，通过删除一些元素或不删除任何元素而从 arr 派生出来的序列。
 *
 *
 *
 * 示例 1：
 *
 * 输入：arr = [1,2,3,4], difference = 1
 * 输出：4
 * 解释：最长的等差子序列是 [1,2,3,4]。
 * 示例 2：
 *
 * 输入：arr = [1,3,5,7], difference = 1
 * 输出：1
 * 解释：最长的等差子序列是任意单个元素。
 * 示例 3：
 *
 * 输入：arr = [1,5,7,8,5,3,4,2,1], difference = -2
 * 输出：4
 * 解释：最长的等差子序列是 [7,5,3,1]。
 *
 *
 * 提示：
 *
 * 1 <= arr.length <= 105
 * -104 <= arr[i], difference <= 104
 * @author SHM
 */
public class LongestSubsequence {
    //超时
    public int longestSubsequence(int[] arr, int difference) {
        int n = arr.length;
        int ans = 1;
        for (int i = 0; i < n-1; i++) {
            int cnt = 1;
            int k = i;
            for (int j = i+1; j < n; j++) {
                if (arr[j]-arr[k]==difference){
                    cnt++;
                    k=j;
                }
            }
            ans=Math.max(ans,cnt);
        }
        return ans;
    }

    /**
     * 方法一：动态规划
     * 下文为方便叙述将 \textit{difference}difference 简写成 dd。
     *
     * 我们从左往右遍历 \textit{arr}arr，并计算出以 \textit{arr}[i]arr[i] 为结尾的最长的等差子序列的长度，取所有长度的最大值，即为答案。
     *
     * 令 \textit{dp}[i]dp[i] 表示以 \textit{arr}[i]arr[i] 为结尾的最长的等差子序列的长度，我们可以在 \textit{arr}[i]arr[i] 左侧找到满足 \textit{arr}[j]=\textit{arr}[i]-darr[j]=arr[i]−d 的元素，将 \textit{arr}[i]arr[i] 加到以 \textit{arr}[j]arr[j] 为结尾的最长的等差子序列的末尾，这样可以递推地从 dp[j]dp[j] 计算出 dp[i]dp[i]。由于我们是从左往右遍历 \textit{arr}arr 的，对于两个相同的元素，下标较大的元素对应的 \textit{dp}dp 值不会小于下标较小的元素对应的 \textit{dp}dp 值，因此下标 jj 可以取满足 j<ij<i 且 \textit{arr}[j]=\textit{arr}[i]-darr[j]=arr[i]−d 的所有下标的最大值。故有转移方程
     *
     * \textit{dp}[i] = \textit{dp}[j] + 1
     * dp[i]=dp[j]+1
     *
     * 由于我们总是在左侧找一个最近的等于 \textit{arr}[i]-darr[i]−d 元素并取其对应 \textit{dp}dp 值，因此我们直接用 \textit{dp}[v]dp[v] 表示以 vv 为结尾的最长的等差子序列的长度，这样 \textit{dp}[v-d]dp[v−d] 就是我们要找的左侧元素对应的最长的等差子序列的长度，因此转移方程可以改为
     *
     * \textit{dp}[v] = \textit{dp}[v-d] + 1
     * dp[v]=dp[v−d]+1
     *
     * 最后答案为 \max\{\textit{dp}\}max{dp}。
     * 复杂度分析
     *
     * 时间复杂度：O(n)O(n)，其中 nn 是数组 \textit{arr}arr 的长度。
     *
     * 空间复杂度：O(n)O(n)。哈希表需要 O(n)O(n) 的空间。
     *
     * 作者：LeetCode-Solution
     * 链接：https://leetcode-cn.com/problems/longest-arithmetic-subsequence-of-given-difference/solution/zui-chang-ding-chai-zi-xu-lie-by-leetcod-xkua/
     *
     * @param arr
     * @param difference
     * @return
     */
    public int longestSubsequence_1(int[] arr, int difference) {
        int ans = 0;
        Map<Integer,Integer> dp = new HashMap<>();
        for (int v : arr) {
            dp.put(v,dp.getOrDefault(v-difference,0)+1);
            ans = Math.max(ans,dp.get(v));
        }
        return ans;
    }
}
